package com.chen.integral.handler;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.chen.base.module.base.dto.Response;
import com.chen.entity.base.login.Admin;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureException;
import org.bouncycastle.util.encoders.Base64;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @Title: manager-spring-mvc-hb
 * @Description: to do
 * @Author: chenjiwei
 * @Date: 2020-11-23 22:10
 * @Version: 1.0.0
 */
    /*
    头部部分header
        “alg”: “HS256”,
        “typ”: “JWT”
    载荷部分payload
        “iss”: “发行者”,
        “sub”: 主题”,
        “aud”: “观众”，
        “exp”:”过期时间”,
        “iat”:”签发时间”*/
public class Tokener {
    /**
     * 签发JWT
     *
     * @param
     * @param subject   可以是JSON数据 尽可能少
     * @param ttlMillis 2*60*60
     * @return String
     *
     */
    public static String createJWT(String subject, Admin admin, long ttlMillis) throws UnsupportedEncodingException {
//        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        Algorithm algorithm = Algorithm.HMAC256("123456");
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        HashMap<String, Object> maps = new HashMap<>();
        maps.put("user","chenjiwei");
        maps.put("orgId","20100");
        JWTCreator.Builder builder = JWT.create()
                .withIssuer("user")
                .withClaim("username", admin.getUsername())
//                .withClaim("role", "admin")
                .withSubject(subject)
                .withExpiresAt(new Date(nowMillis + ttlMillis))
                .withIssuedAt(now)
                .withJWTId(UUID.randomUUID().toString());
        return builder.sign(algorithm).toString();
    }

    public static void main(String[] args) throws UnsupportedEncodingException {
//        String token = createJWT("111111", "cjwwww", 800000);
//        System.out.println(token);
//        String s = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxMTExMTEiLCJzdWIiOiJjand3d3ciLCJpc3MiOiJ1c2VyIiwiaWF0IjoxNjA2MTQzMDI3LCJleHAiOjE2MDYxNDM4Mjd9.wpurBy7QGSXP4dqXppvT-mlUZ1R2g-f-1kx0-tLwh_0";
//        Response response = validateJWT(token);
//        System.out.println(response.getData());
    }

    /**
     * 验证JWT
     *
     * @param jwtStr
     * @return
     */
    public static Response validateJWT(String jwtStr) {
        try {
            Admin admin = verifyToken(jwtStr);
            return Response.success("验证通过", admin);
        } catch (ExpiredJwtException | TokenExpiredException e) {
            e.printStackTrace();
            return Response.fail("token过期");
        } catch (SignatureException e) {
            e.printStackTrace();
            return Response.fail("验证失败");
        } catch (Exception e) {
            e.printStackTrace();
            return Response.fail("验证异常");
        }
    }

    public static SecretKey generalKey() {
        byte[] encodedKey = Base64.decode("123456");
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }

    /**
     *
     * 解析JWT字符串
     *
     * @param jwt
     * @return
     * @throws Exception
     */
    public static Claims parseJWT(String jwt) throws Exception {
//        SecretKey secretKey = generalKey();

        return Jwts.parser().setSigningKey("123456").parseClaimsJws(jwt).getBody();
    }

    public static Admin verifyToken(String token) throws TokenExpiredException {
        Algorithm algorithm = null;
        try {
            algorithm = Algorithm.HMAC256("123456");
        } catch (IllegalArgumentException | UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        JWTVerifier verifier = JWT.require(algorithm).withIssuer("user").build();
        DecodedJWT jwt =  verifier.verify(token);
        Map<String, Claim> map = jwt.getClaims();
        Admin admin = new Admin();
        admin.setUsername(map.get("username").asString());
        return admin;
    }

}
